package tree;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class HashTree<T, E> {
	private final Map<T, TreeNode<T, E>> nodeMap = new HashMap<T, TreeNode<T, E>>();
	private final Map<T, List<TreeNode<T, E>>> listMap = new HashMap<T, List<TreeNode<T, E>>>();

	public HashTree() {
	}

	/**
	 * <方法描述>添加一个节点
	 * 
	 * @param node
	 *            节点
	 */
	public void addNode(TreeNode<T, E> node) {
		if (nodeMap.containsKey(node.getId())) {
			return;
		}
		nodeMap.put(node.getId(), node);
		List<TreeNode<T, E>> list = listMap.get(node.getPid());
		if (list == null) {
			list = new ArrayList<TreeNode<T, E>>();
			listMap.put(node.getPid(), list);
		}
		TreeNode<T, E> parentNode = nodeMap.get(node.getPid());
		if (parentNode != null) {
			node.setLevel(parentNode.getLevel() + 1);
		} else {
			List<TreeNode<T, E>> childs = this.getChildNodes(node.getId());
			if (childs != null && childs.size() > 1) {
				TreeNode<T, E> child = childs.get(0);
				node.setLevel(child.getLevel());
			}
		}
		list.add(node);
		setLeafFalse(node);
		initChildLevel(node);
	}

	private void initChildLevel(TreeNode<T, E> node) {
		List<TreeNode<T, E>> list = this.getChildNodes(node.getId());
		for (TreeNode<T, E> child : list) {
			child.setLevel(node.getLevel() + 1);
			initChildLevel(child);
		}
	}

	private void setLeafFalse(TreeNode<T, E> node) {
		TreeNode<T, E> parentNode = nodeMap.get(node.getPid());
		if (parentNode != null) {
			parentNode.setLeaf(false);
			setLeafFalse(parentNode);
		} else if (this.hasChildNode(node)) {
			node.setLeaf(false);
		}
	}

	/**
	 * <方法描述>获取根节点的ID
	 * 
	 * @return
	 */
	public T getRootId() {
		T rootId = null;
		for (TreeNode<T, E> node : nodeMap.values()) {
			if (rootId == null) {
				T id = node.getId();
				if (id instanceof String) {
					rootId = (T) "";
				} else if (id instanceof Integer) {
					rootId = (T) Integer.valueOf(0);
				}
			}
			if (node.getLevel() == 0) {
				rootId = node.getPid();
				break;
			}
		}
		return rootId;
	}

	/**
	 * 删除一个节点
	 * 
	 * @param node
	 */
	public void delNode(T id) {
		TreeNode<T, E> node = this.getNode(id);
		if (node == null)
			return;
		List<TreeNode<T, E>> childList = this.getChildNodes(id);
		nodeMap.remove(id);
		listMap.remove(id);
		if (childList == null)
			return;
		for (TreeNode<T, E> childNode : childList) {
			delNode(childNode.getId());
		}
	}

	/**
	 * 取一个节点
	 * 
	 * @param id
	 * @return
	 */
	public TreeNode<T, E> getNode(T id) {
		return nodeMap.get(id);
	}

	/**
	 * 删除下级节点
	 * 
	 * @param pid
	 */
	public void delChildNodes(T pid) {
		List<TreeNode<T, E>> childList = this.getChildNodes(pid);
		if (childList == null)
			return;
		for (TreeNode<T, E> childNode : childList) {
			nodeMap.remove(childNode.getId());
			listMap.remove(childNode.getId());
		}
		listMap.remove(pid);
	}

	/**
	 * 取下级节点
	 * 
	 * @param pid
	 * @return
	 */
	public List<TreeNode<T, E>> getChildNodes(T pid) {
		List<TreeNode<T, E>> obj = listMap.get(pid);
		if (obj == null) {
			return new ArrayList<TreeNode<T, E>>();
		}
		return obj;
	}

	/**
	 * 取下级节点对象
	 * 
	 * @param pid
	 * @return
	 */
	public List<E> getChildObject(T pid) {
		List<E> list = new ArrayList<E>();
		List<TreeNode<T, E>> obj = listMap.get(pid);
		if (obj != null) {
			for (TreeNode<T, E> node : obj) {
				list.add(node.getBean());
			}
		}
		return list;
	}

	/**
	 * 取下级所有节点
	 * 
	 * @param pid
	 * @return
	 */
	public List<TreeNode<T, E>> getAllChildNodes(T pid) {
		List<TreeNode<T, E>> list = new ArrayList<TreeNode<T, E>>();
		List<TreeNode<T, E>> obj = listMap.get(pid);
		if (obj != null) {
			for (TreeNode<T, E> node : obj) {
				list.add(node);
				list.addAll(getAllChildNodes(node.getId()));
			}
		}
		return list;
	}


	/**
	 * 取下级所有节点
	 * @param pid
	 * @param isSelf 是否包括自己
	 * @return
	 */
	public List<TreeNode<T, E>> getAllChildNodes(T pid, boolean isSelf) {
		List<TreeNode<T, E>> list = this.getAllChildNodes(pid);
		if (!isSelf) {
			return list;
		}
		list.add(nodeMap.get(pid));
		return list;
	}

	/**
	 * 取下级所有节点对象
	 * 
	 * @param pid
	 * @return
	 */
	public List<E> getAllChildObject(T pid) {
		List<E> list = new ArrayList<E>();
		List<TreeNode<T, E>> obj = listMap.get(pid);
		if (obj != null) {
			for (TreeNode<T, E> node : obj) {
				list.add(node.getBean());
				list.addAll(getAllChildObject(node.getId()));
			}
		}
		return list;
	}
	
	/**
	 * 取下级所有节点对象
	 * @param pid
	 * @param isSelf 是否包括自己
	 * @return
	 */
	public List<E> getAllChildObject(T pid, boolean isSelf) {
		List<E> list = this.getAllChildObject(pid);
		if (!isSelf) {
			return list;
		}
		list.add(nodeMap.get(pid).getBean());
		return list;
	}
	
	
	

	/**
	 * <方法描述> 获取当前对象的上级节点
	 * 
	 * @param id
	 * @return
	 */
	public TreeNode<T, E> getParentNode(T id) {
		TreeNode<T, E> parentNode = null;
		TreeNode<T, E> node = nodeMap.get(id);
		if (node != null) {
			T pid = node.getPid();
			parentNode = nodeMap.get(pid);
		}
		return parentNode;
	}

	/**
	 * <方法描述> 获取当前对象的上级节点
	 * 
	 * @param id
	 * @return
	 */
	public E getParentObject(T id) {
		E parentObject = null;
		TreeNode<T, E> parentNode = getParentNode(id);
		if (parentNode != null) {
			parentObject = parentNode.getBean();
		}
		return parentObject;
	}

	/**
	 * 取上级所有节点
	 * 
	 * @param id
	 * @return
	 */
	public List<TreeNode<T, E>> getAllParentNodes(T id) {
		List<TreeNode<T, E>> list = new ArrayList<TreeNode<T, E>>();
		TreeNode<T, E> node = nodeMap.get(id);
		if (node != null) {
			T pid = node.getPid();
			if (pid != null) {
				TreeNode<T, E> parentNode = nodeMap.get(pid);
				while (parentNode != null) {
					list.add(parentNode);
					if (parentNode.getPid() != null) {
						parentNode = nodeMap.get(parentNode.getPid());
					} else {
						parentNode = null;
					}
				}
			}
		}
		return list;
	}

	/**
	 * 取上级所有节点对象
	 * 
	 * @param id
	 * @return
	 */
	public List<E> getAllParentObject(T id) {
		List<E> list = new ArrayList<E>();
		TreeNode<T, E> node = nodeMap.get(id);
		if (node != null) {
			T pid = node.getPid();
			if (pid != null) {
				TreeNode<T, E> parentNode = nodeMap.get(pid);
				while (parentNode != null) {
					list.add(parentNode.getBean());
					if (parentNode.getPid() != null) {
						parentNode = nodeMap.get(parentNode.getPid());
					} else {
						parentNode = null;
					}
				}
			}
		}
		return list;
	}

	/**
	 * 判断该节点是否有子节点
	 * 
	 * @description: <方法描述>
	 * @param node
	 * @return
	 */
	public boolean hasChildNode(TreeNode<T, E> node) {
		return (listMap.get(node.getId()) != null);
	}

	@Override
	public String toString() {
		StringBuffer sb = new StringBuffer();
		sb.append("[");
		for (TreeNode<T, E> node : nodeMap.values()) {
			if (sb.length() != 1) {
				sb.append(",");
			}
			sb.append("{id:" + node.getId() + ",pid:" + node.getPid() + ",value:" + node.getBean() + ",open:"
					+ node.isOpen() + ",clickable:" + node.isClickable() + ",leaf:" + node.isLeaf() + ",level:"
					+ node.getLevel() + "}");
		}
		sb.append("]");
		return sb.toString();
	}
}
